/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MYAPPLICATION_FILETRANSFER_H
#define MYAPPLICATION_FILETRANSFER_H

#include "CordovaPlugin.h"
#include "cJSON.h"

class FileTransfer:public CordovaPlugin {
    static const int LOG_PRINT_DOMAIN = 0xff00;
    enum error_code {
    FILE_NOT_FOUND_ERR = 1,
    INVALID_URL_ERR = 2,
    CONNECTION_ERR = 3,
    ABORTED_ERR = 4,
    NOT_MODIFIED_ERR = 5
    };
    struct FileUploadResult {
        int m_nByteSent;
        int m_nResponseCode;
        string m_strResponse;
        string m_strObjectId;
    };
    struct FileProgressResult {
        int m_nLoaded;
        int m_nTotal;
        bool m_lengthComputable;
    };
    class HttpRequest : public CThread{
        string m_strMethod;
        cJSON* m_pArgs{nullptr};
        CallbackContext m_cbc;
        FileTransfer* m_fileTransfer;
        int m_nTempBufSize{0};
        string m_strReqId;
        std::atomic<bool> m_isAbort{false};
    public:
        void Execute(void* arg);
        void SetFileTransfer(FileTransfer* fileTransfer, const string& strMethod, cJSON* pJson, CallbackContext cbc) {
            m_fileTransfer = fileTransfer;
            m_strMethod = strMethod;
            m_pArgs = pJson;
            m_cbc = cbc;
        }
        void* InitThreadData();
	    void DeInitThreadData(void* pArg);
        void setReqId(const string strReqId) {m_strReqId = strReqId;}
        string getReqId() const { return m_strReqId;}
        void setAbort(){m_isAbort.store(true);};
        std::atomic<bool>& getAbort() {return m_isAbort;}
    };
    std::mutex m_mutex;
    vector<HttpRequest*> m_vecHttpRequestThread;
    void setHttpRequestThread(const HttpRequest* pRequest);
    bool setHttpRequestThreadAbort(const string strReqId);
    static const string LINE_START;
    static const string LINE_END;
    static const string BOUNDARY;
public:
    FileTransfer(){
    }
    ~FileTransfer() {
    };
    bool execute(const string&  actionAsString, cJSON* args, CallbackContext cbc) override;
    void upload(const string& strSource, const string& strTarget, cJSON* args, void* pBuf, const int nLength,  CallbackContext cbc, HttpRequest* pRequest);
    void download(const string& strSource, const string& strTarget, cJSON* args, void* pBuf, const int nLength,  CallbackContext cbc, HttpRequest* pRequest);
    static string getArgument(cJSON* args, int position, string defaultString);
    cJSON* createFileTransferError(int errorCode, string source, string target, string body, int httpStatus, string msg);
    cJSON* createFileTransferResult(FileUploadResult result);
};

#endif //MYAPPLICATION_FILETRANSFER_H
